#ifdef KITSCHY_DEBUG_MEMORY 
#include "debug_memorymanager.h"
#endif

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "stdarg.h"
#include "assert.h"

#include "BList.h"

#include "symbol.h"
#include "sort.h"
#include "ontology.h"
#include "featureterm.h"
#include "FTKBase.h"

#include "SpecialTerm.h"



char *FeatureTerm::toStringNOOS(void)
{
	return toStringNOOS(0);
} /* FeatureTerm::toStringNOOS */ 


char *FeatureTerm::toStringNOOS(FTKBase *dm)
{
	char *tmp=0;
	List<FeatureTermContainer> bindings;
	List<char> tokens;

	toStringNOOSInternal(&tokens,&bindings,0,dm);

	{
		int len,pos,i;
		char *token;
		char tmp2[80],tmp4[80],*tmp3;

		len=0;
		tokens.Rewind();
		while(tokens.Iterate(token)) {
			len+=strlen(token)+1;
		} /* while */ 
		len++;

		tmp=new char[len];

		pos=0;
		tokens.Rewind();
		while(tokens.Iterate(token)) {
			sprintf(tmp+pos,"%s",token);
			pos+=strlen(token);
		} /* while */ 
		tmp[pos]=0;


		// Search for nonused variables, and remove them: 
		for(i=0;i<bindings.Length();i++) {
			sprintf(tmp2,"!X%i)",i+1);
			sprintf(tmp4,"!X%i\n",i+1);
			if (strstr(tmp,tmp2)==0 && strstr(tmp,tmp4)==0) {
				// delete variable:  
				sprintf(tmp2,"?X%i ",i+1);
				tmp3=strstr(tmp,tmp2);
				if (tmp3) {
					strcpy(tmp3,tmp3+strlen(tmp2));
				} // if 
			} // if  
		} // for  

	}

	while(!bindings.EmptyP()) bindings.ExtractIni();
	
	return tmp;
} /* FeatureTerm::toStringNOOS */ 



void FeatureTerm::toStringNOOSInternal(List<char> *tokens,List<FeatureTermContainer> *bindings,int tabs,FTKBase *dm)
{
	int i;
	char *tmp;
	char *token;
	int ID=-1;

	tmp=new char[1024];

	if (m_ft->m_name!=0 && dm!=0 && dm->MemberP(this)) {
		sprintf(tmp,"%s",m_ft->m_name->get());
		token=new char[strlen(tmp)+1];
		strcpy(token,tmp);
		tokens->Add(token);
		delete []tmp;
		return;
	} /* if */ 

	ID=bindings->PositionRef(m_ft);

	if (ID==-1) {
		bindings->Add(m_ft);
		ID=bindings->PositionRef(m_ft);

		switch(m_ft->m_data_type) {
		case DATATYPE_ABSTRACT:
			{
				sprintf(tmp,"(define ?X%i ",ID+1);
				token=new char[strlen(tmp)+1];
				strcpy(token,tmp);
				tokens->Add(token);

				sprintf(tmp,"(%s",m_ft->m_sort->get());
				token=new char[strlen(tmp)+1];
				strcpy(token,tmp);
				tokens->Add(token);

				if (m_ft->m_name!=0) {
					sprintf(tmp," :id %s",m_ft->m_name->get());
					token=new char[strlen(tmp)+1];
					strcpy(token,tmp);
					tokens->Add(token);					
				} /* if */ 

				sprintf(tmp,"))");
				token=new char[strlen(tmp)+1];
				strcpy(token,tmp);
				tokens->Add(token);	
			}
			break;
		case DATATYPE_INTEGER:
			if (m_ft->m_value.m_i.m_type==-1) {
				sprintf(tmp,"(define ?X%i (integer))",ID+1);
			} else {
				sprintf(tmp,"?X%i %i",ID+1,m_ft->m_value.m_i.m_value);
			} /* if */ 
			token=new char[strlen(tmp)+1];
			strcpy(token,tmp);
			tokens->Add(token);
			break;
		case DATATYPE_FLOAT:
			if (m_ft->m_value.m_f.m_type==-1) {
				sprintf(tmp,"(define ?X%i (float))",ID+1);
			} else {
				sprintf(tmp,"%f",m_ft->m_value.m_f.m_value);
			} /* if */ 
			token=new char[strlen(tmp)+1];
			strcpy(token,tmp);
			tokens->Add(token);
			break;
		case DATATYPE_SYMBOL:
			if (m_ft->m_value.m_s==0) {
				sprintf(tmp,"(define ?X%i (symbol))",ID+1);
				token=new char[strlen(tmp)+1];
				strcpy(token,tmp);
				tokens->Add(token);
			} else {
				if (strlen(m_ft->m_value.m_s->get())+10>1024) {
					delete []tmp;
					tmp = new char[strlen(m_ft->m_value.m_s->get())+10];
				}
				sprintf(tmp,"?X%i \"%s\"",ID+1,m_ft->m_value.m_s->get());
				token=new char[strlen(tmp)+1];
				strcpy(token,tmp);
				tokens->Add(token);
			} /* if */ 
			break;
		case DATATYPE_FEATURETERM:
			{
				List<FeatureTerm> l;
				FeatureTerm *f;
				List<Symbol> l2;
				Symbol *s;

				sprintf(tmp,"(define ?X%i ",ID+1);
				token=new char[strlen(tmp)+1];
				strcpy(token,tmp);
				tokens->Add(token);

				sprintf(tmp,"(%s",m_ft->m_sort->get());
				token=new char[strlen(tmp)+1];
				strcpy(token,tmp);
				tokens->Add(token);

				if (m_ft->m_name!=0) {
					sprintf(tmp," :id %s",m_ft->m_name->get());
					token=new char[strlen(tmp)+1];
					strcpy(token,tmp);
					tokens->Add(token);					
				} /* if */ 

				sprintf(tmp,")");
				token=new char[strlen(tmp)+1];
				strcpy(token,tmp);
				tokens->Add(token);	

				l.Instance(*(m_ft->m_value.m_ft.m_feature_value));
				l2.Instance(*(m_ft->m_value.m_ft.m_feature_name));
				l.Rewind();
				l2.Rewind();

				if (!l.EmptyP()) {
					sprintf(tmp,"\n");
					token=new char[strlen(tmp)+1];
					strcpy(token,tmp);
					tokens->Add(token);	
					/* tab: */ 
					for(i=0;i<tabs+2;i++) tmp[i]=' ';
					tmp[i]=0;
					token=new char[strlen(tmp)+1];
					strcpy(token,tmp);
					tokens->Add(token);
				} /* if */ 

				while(l.Iterate(f) && l2.Iterate(s)) {
					sprintf(tmp,"(%s ",s->get());
					token=new char[strlen(tmp)+1];
					strcpy(token,tmp);
					tokens->Add(token);	

					f->toStringNOOSInternal(tokens,bindings,tabs+strlen(token)+2,dm);

					sprintf(tmp,")");
					token=new char[strlen(tmp)+1];
					strcpy(token,tmp);
					tokens->Add(token);	

					if (!l.EndP()) {
						sprintf(tmp,"\n");
						token=new char[strlen(tmp)+1];
						strcpy(token,tmp);
						tokens->Add(token);	
						/* tab: */ 
						for(i=0;i<tabs+2;i++) tmp[i]=' ';
						tmp[i]=0;
						token=new char[strlen(tmp)+1];
						strcpy(token,tmp);
						tokens->Add(token);
					} /* if */ 
				} /* while */ 

				sprintf(tmp,")");
				token=new char[strlen(tmp)+1];
				strcpy(token,tmp);
				tokens->Add(token);	

			}
			
			break;
		case DATATYPE_SET:
			{
				List<FeatureTerm> l;
				FeatureTerm *f;

				sprintf(tmp,"(define ?X%i (set)",ID+1);
				token=new char[strlen(tmp)+1];
				strcpy(token,tmp);
				tokens->Add(token);

				l.Instance(*(m_ft->m_value.m_set));
				l.Rewind();

				if (!l.EmptyP()) {
					sprintf(tmp,"\n");
					token=new char[strlen(tmp)+1];
					strcpy(token,tmp);
					tokens->Add(token);	
					/* tab: */ 
					for(i=0;i<tabs+2;i++) tmp[i]=' ';
					tmp[i]=0;
					token=new char[strlen(tmp)+1];
					strcpy(token,tmp);
					tokens->Add(token);
				} /* if */ 

				while(l.Iterate(f)) {
					f->toStringNOOSInternal(tokens,bindings,tabs+1,dm);

					if (!l.EndP()) {
						sprintf(tmp,"\n");
						token=new char[strlen(tmp)+1];
						strcpy(token,tmp);
						tokens->Add(token);	
						/* tab: */ 
						for(i=0;i<tabs+2;i++) tmp[i]=' ';
						tmp[i]=0;
						token=new char[strlen(tmp)+1];
						strcpy(token,tmp);
						tokens->Add(token);
					} /* if */ 
				} /* while */ 

				sprintf(tmp,")");
				token=new char[strlen(tmp)+1];
				strcpy(token,tmp);
				tokens->Add(token);
			}
			break;

		case DATATYPE_SPECIAL:
			{
				List<FeatureTerm> l;
				FeatureTerm *f;
				List<Symbol> l2;
				Symbol *s;

				sprintf(tmp,"(define ?X%i ",ID+1);
				token=new char[strlen(tmp)+1];
				strcpy(token,tmp);
				tokens->Add(token);

				sprintf(tmp,"(%s",m_ft->m_sort->get());
				token=new char[strlen(tmp)+1];
				strcpy(token,tmp);
				tokens->Add(token);

				if (m_ft->m_name!=0) {
					sprintf(tmp," :id %s",m_ft->m_name->get());
					token=new char[strlen(tmp)+1];
					strcpy(token,tmp);
					tokens->Add(token);					
				} /* if */ 

				sprintf(tmp,")");
				token=new char[strlen(tmp)+1];
				strcpy(token,tmp);
				tokens->Add(token);	

				l.Instance((m_ft->m_value.m_special->m_values));
				l2.Instance((m_ft->m_value.m_special->m_names));
				l.Rewind();
				l2.Rewind();

				if (!l.EmptyP()) {
					sprintf(tmp,"\n");
					token=new char[strlen(tmp)+1];
					strcpy(token,tmp);
					tokens->Add(token);	
					/* tab: */ 
					for(i=0;i<tabs+2;i++) tmp[i]=' ';
					tmp[i]=0;
					token=new char[strlen(tmp)+1];
					strcpy(token,tmp);
					tokens->Add(token);
				} /* if */ 

				while(l.Iterate(f) && l2.Iterate(s)) {
					sprintf(tmp,"(%s ",s->get());
					token=new char[strlen(tmp)+1];
					strcpy(token,tmp);
					tokens->Add(token);	

					f->toStringNOOSInternal(tokens,bindings,tabs+strlen(token)+2,dm);

					sprintf(tmp,")");
					token=new char[strlen(tmp)+1];
					strcpy(token,tmp);
					tokens->Add(token);	

					if (!l.EndP()) {
						sprintf(tmp,"\n");
						token=new char[strlen(tmp)+1];
						strcpy(token,tmp);
						tokens->Add(token);	
						/* tab: */ 
						for(i=0;i<tabs+2;i++) tmp[i]=' ';
						tmp[i]=0;
						token=new char[strlen(tmp)+1];
						strcpy(token,tmp);
						tokens->Add(token);
					} /* if */ 
				} /* while */ 

				sprintf(tmp,")");
				token=new char[strlen(tmp)+1];
				strcpy(token,tmp);
				tokens->Add(token);	

			}
			
			break;
		} /* switch */ 
	} else {
		sprintf(tmp,"!X%i",ID+1);
		token=new char[strlen(tmp)+1];
		strcpy(token,tmp);
		tokens->Add(token);
	} /* if */ 

	delete []tmp;

} /* FeatureTerm::toStringNOOSInternal */ 


